//
// Created on 2024/8/24.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef ISSUETEST_BASE_NODE_H
#define ISSUETEST_BASE_NODE_H

#include "./node_api_provider.h"
#include <list>
#include <memory>

namespace NativeArkUI {
class ArkUIBaseNode {
public:
    ArkUIBaseNode(ArkUI_NodeType type) {
        arkUINativeNodeApi = NodeApiProvider::GetInstance()->GetNativeNodeAPI();
        nodeHandle = arkUINativeNodeApi->createNode(type);
        registerEventReceiver();
    }
    ~ArkUIBaseNode() {
        // 反注册事件接收器
        unregisterEventReceiver();
        // 封装析构函数，实现子节点移除功能。
        if (!children_.empty()) {
            for (const auto &child : children_) {
                arkUINativeNodeApi->removeChild(nodeHandle, child->GetNodeHandle());
            }
            children_.clear();
        }
        // 封装析构函数，统一回收节点资源。
        arkUINativeNodeApi->disposeNode(nodeHandle);
    }

    void AddChild(const std::shared_ptr<ArkUIBaseNode> &child) {
        children_.emplace_back(child);
        OnAddChild(child);
    }

    std::shared_ptr<ArkUIBaseNode> GetChildAt(int32_t position) {
        if (position >= 0 && position < children_.size()) {
            auto it = children_.begin();
            std::advance(it, position); // 移动迭代器到第n个位置
            return *it;
        } else {
            return nullptr;
        }
    }

    void RemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) {
        children_.remove(child);
        OnRemoveChild(child);
    }

    void InsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) {
        if (index >= children_.size()) {
            AddChild(child);
        } else {
            auto iter = children_.begin();
            std::advance(iter, index);
            children_.insert(iter, child);
            OnInsertChild(child, index);
        }
    }
    /**
     * 添加点击事件
     */
    void SetOnClickListener(const std::function<void()> &onClick) {
        onClick_ = onClick;
        OnClickListener(onClick);
    }
    /**
     * 添加触摸事件
     */
    void SetOnTouchListener(const std::function<void(int32_t type, float x, float y)> &onTouch) {
        onTouch_ = onTouch;
        OnTouchListener(onTouch);
    }
    /**
     * 添加组件销毁事件
     */
    void SetOnDisappearCallback(const std::function<void()> &onDisappear) {
        onDisappear_ = onDisappear;
        OnDisappearCallback(onDisappear);
    }
    /**
     * 添加组件挂载事件
     */
    void SetOnAppearCallback(const std::function<void()> &onAppear) {
        onAppear_ = onAppear;
        OnAppearCallback(onAppear);
    }
    /**
     * 设置onMeasure回调事件
     */
    void SetOnMeasureCallback(const std::function<void(ArkUI_DrawContext *drawContext)> &onMeasure) {
        onMeasure_ = onMeasure;
        OnMeasureCallback(onMeasure);
    }
    /**
     * 设置onLayout回调事件
     */
    void SetOnLayoutCallback(const std::function<void(ArkUI_DrawContext *drawContext)> &onLayout) {
        onLayout_ = onLayout;
        OnLayoutCallback(onLayout);
    }
    /**
     * 设置onDraw回调事件
     */
    void SetOnDrawCallback(const std::function<void(ArkUI_DrawContext *drawContext)> &onDraw) {
        onDraw_ = onDraw;
        OnDrawCallback(onDraw);
    }
    /**
     * 设置onForeground回调事件
     */
    void SetOnForegroundCallback(const std::function<void(ArkUI_DrawContext *drawContext)> &onForeground) {
        onForeground_ = onForeground;
        OnForegroundCallback(onForeground);
    }
    /**
     * 设置onOverlayDraw回调事件
     */
    void SetOnOverlayDrawCallback(const std::function<void(ArkUI_DrawContext *drawContext)> &onOverlay) {
        onOverlay_ = onOverlay;
        OnOverlayDrawCallback(onOverlay);
    }

    ArkUI_NodeHandle GetNodeHandle() const { return nodeHandle; }

protected:
    ArkUI_NativeNodeAPI_1 *arkUINativeNodeApi = nullptr;
    ArkUI_NodeHandle nodeHandle;
    // 针对父容器子类需要重载下面的函数。
    virtual void OnAddChild(const std::shared_ptr<ArkUIBaseNode> &child) {}
    virtual void OnRemoveChild(const std::shared_ptr<ArkUIBaseNode> &child) {}
    virtual void OnInsertChild(const std::shared_ptr<ArkUIBaseNode> &child, int32_t index) {}
    virtual void OnClickListener(const std::function<void()> &onClick) {}
    virtual void OnTouchListener(const std::function<void(int32_t type, float x, float y)> &onTouch) {}
    virtual void OnDisappearCallback(const std::function<void()> &onDisappear) {}
    virtual void OnAppearCallback(const std::function<void()> &onAppear) {}
    virtual void OnMeasureCallback(const std::function<void(ArkUI_DrawContext *drawContext)> &onMeasure) {}
    virtual void OnLayoutCallback(const std::function<void(ArkUI_DrawContext *drawContext)> &onLayout) {}
    virtual void OnDrawCallback(const std::function<void(ArkUI_DrawContext *drawContext)> &onDraw) {}
    virtual void OnForegroundCallback(const std::function<void(ArkUI_DrawContext *drawContext)> &onForeground) {}
    virtual void OnOverlayDrawCallback(const std::function<void(ArkUI_DrawContext *drawContext)> &onOverlayDraw) {}
    virtual void OnNodeEvent(ArkUI_NodeEvent *event) {}
    virtual void OnDrawEvent(ArkUI_NodeCustomEvent *event) {}

    // 事件监听器函数指针。
    static void NodeEventReceiver(ArkUI_NodeEvent *event) {
        // 获取事件发生的UI组件对象。
        auto nodeHandle = OH_ArkUI_NodeEvent_GetNodeHandle(event);
        // 获取保持在UI组件对象中的自定义数据，返回封装类指针。
        auto *node = reinterpret_cast<ArkUIBaseNode *>(
            NodeApiProvider::GetInstance()->GetNativeNodeAPI()->getUserData(nodeHandle));
        // 基于封装类实例对象处理事件。
        node->ProcessNodeEvent(event);
    }
    void ProcessNodeEvent(ArkUI_NodeEvent *event) {
        auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
        switch (eventType) {
        case NODE_ON_CLICK: {
            if (onClick_) {
                onClick_();
            }
            break;
        }
        case NODE_TOUCH_EVENT: {
            if (onTouch_) {
                auto *uiInputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
                float x = OH_ArkUI_PointerEvent_GetX(uiInputEvent);
                float y = OH_ArkUI_PointerEvent_GetY(uiInputEvent);
                auto type = OH_ArkUI_UIInputEvent_GetAction(uiInputEvent);
                onTouch_(type, x, y);
            }
        }
        case NODE_EVENT_ON_DISAPPEAR: {
            if (onDisappear_) {
                onDisappear_();
            }
            break;
        }
        case NODE_EVENT_ON_APPEAR: {
            if (onAppear_) {
                onAppear_();
            }
            break;
        }
        default: {
            // 组件特有事件交给子类处理
            OnNodeEvent(event);
        }
        }
    }
    // 绘制事件监听器函数指针。
    static void DrawEventReceiver(ArkUI_NodeCustomEvent *event) {
        // 获取事件发生的UI组件对象。
        auto nodeHandle = OH_ArkUI_NodeCustomEvent_GetNodeHandle(event);
        // 获取保持在UI组件对象中的自定义数据，返回封装类指针。
        auto *node = reinterpret_cast<ArkUIBaseNode *>(
            NodeApiProvider::GetInstance()->GetNativeNodeAPI()->getUserData(nodeHandle));
        // 基于封装类实例对象处理事件。
        node->ProcessDrawEvent(event);
    }
    void ProcessDrawEvent(ArkUI_NodeCustomEvent *event) {
        auto drawType = OH_ArkUI_NodeCustomEvent_GetEventType(event);
        auto drawContext = OH_ArkUI_NodeCustomEvent_GetDrawContextInDraw(event);
        switch (drawType) {
        case ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE: {
            if (onMeasure_) {
                onMeasure_(drawContext);
            }
            break;
        }
        case ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT: {
            if (onLayout_) {
                onLayout_(drawContext);
            }
        }
        case ARKUI_NODE_CUSTOM_EVENT_ON_DRAW: {
            if (onDraw_) {
                onDraw_(drawContext);
            }
            break;
        }
        case ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW: {
            if (onForeground_) {
                onForeground_(drawContext);
            }
            break;
        }
        case ARKUI_NODE_CUSTOM_EVENT_ON_OVERLAY_DRAW: {
            if (onOverlay_) {
                onOverlay_(drawContext);
            }
            break;
        }
        default: {
            // 组件特有事件交给子类处理
            OnDrawEvent(event);
        }
        }
    }


private:
    std::list<std::shared_ptr<ArkUIBaseNode>> children_;
    std::function<void()> onClick_;
    std::function<void()> onDisappear_;
    std::function<void()> onAppear_;
    std::function<void(int32_t type, float x, float y)> onTouch_;
    std::function<void(ArkUI_DrawContext *drawContext)> onMeasure_;
    std::function<void(ArkUI_DrawContext *drawContext)> onLayout_;
    std::function<void(ArkUI_DrawContext *drawContext)> onDraw_;
    std::function<void(ArkUI_DrawContext *drawContext)> onForeground_;
    std::function<void(ArkUI_DrawContext *drawContext)> onOverlay_;

    void unregisterEventReceiver() {
        if (onClick_) {
            arkUINativeNodeApi->unregisterNodeEvent(nodeHandle, NODE_ON_CLICK);
        }
        if (onTouch_) {
            arkUINativeNodeApi->unregisterNodeEvent(nodeHandle, NODE_TOUCH_EVENT);
        }
        if (onDisappear_) {
            arkUINativeNodeApi->unregisterNodeEvent(nodeHandle, NODE_EVENT_ON_DISAPPEAR);
        }
        if (onAppear_) {
            arkUINativeNodeApi->unregisterNodeEvent(nodeHandle, NODE_EVENT_ON_APPEAR);
        }
        if (onMeasure_) {
            arkUINativeNodeApi->unregisterNodeCustomEvent(nodeHandle, ARKUI_NODE_CUSTOM_EVENT_ON_MEASURE);
        }
        if (onDraw_) {
            arkUINativeNodeApi->unregisterNodeCustomEvent(nodeHandle, ARKUI_NODE_CUSTOM_EVENT_ON_DRAW);
        }
        if (onLayout_) {
            arkUINativeNodeApi->unregisterNodeCustomEvent(nodeHandle, ARKUI_NODE_CUSTOM_EVENT_ON_LAYOUT);
        }
        if (onForeground_) {
            arkUINativeNodeApi->unregisterNodeCustomEvent(nodeHandle, ARKUI_NODE_CUSTOM_EVENT_ON_FOREGROUND_DRAW);
        }
        if (onOverlay_) {
            arkUINativeNodeApi->unregisterNodeCustomEvent(nodeHandle, ARKUI_NODE_CUSTOM_EVENT_ON_OVERLAY_DRAW);
        }
        arkUINativeNodeApi->removeNodeEventReceiver(nodeHandle, NodeEventReceiver);
        arkUINativeNodeApi->removeNodeCustomEventReceiver(nodeHandle, DrawEventReceiver);
    }

    void registerEventReceiver() {
        // 事件触发时需要通过函数获取对应的事件对象，这边通过设置节点自定义数据将封装类指针保持在组件上，方便后续事件分发。
        arkUINativeNodeApi->setUserData(nodeHandle, this);
        // 注册节点监听事件接收器。
        arkUINativeNodeApi->addNodeEventReceiver(nodeHandle, NodeEventReceiver);
        // 注册节点绘制事件接收器。
        arkUINativeNodeApi->addNodeCustomEventReceiver(nodeHandle, DrawEventReceiver);
    }
};
} // namespace NativeArkUI

#endif // ISSUETEST_BASE_NODE_H
